home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #42 (Mar 89) / calc source / Parser.c < prev    next >
Text File  |  1989-02-09  |  8KB  |  380 lines

  1.  
  2. #include <WindowMgr.h>
  3. #include <ListMgr.h>
  4. #include <OSUtil.h>
  5. #include <EventMgr.h>
  6.  
  7. #include <Strings.h>
  8. #include <Math.h>
  9. #include <Ctype.h>
  10. #include <Stdio.h>
  11.  
  12. #include "MacCalc.h"
  13. #include "CalcData.h"
  14. #include "Parser.h"
  15.  
  16. unsigned char *curr_pos = NULL ;
  17. int parse_err = 0 ;
  18. Str255 buffer ;
  19.  
  20. /* Simple algabraic expression parser */
  21.  
  22. double ParseFormula( formula, error )
  23. unsigned char *formula ;
  24. int *error ;
  25. {
  26.     register double value ;
  27.  
  28.     /* convert into c string in buffer */
  29.     BlockMove( &formula[2], buffer, formula[0]-1 ) ;
  30.     buffer[formula[0]-1] = 0 ;  /* 0 terminate buffer */
  31.     
  32.     curr_pos = buffer ;
  33.     parse_err = 0 ;
  34.     
  35.     value = ParseExpression( ) ;
  36.     
  37.     *error = parse_err ;        /* Set error flag */
  38.     
  39.     return ( value ) ;
  40. }
  41. double ParseExpression( )
  42. {
  43.     register double val ;
  44.     
  45.     val = ParseFactor( ) ;
  46.     
  47.     switch( *curr_pos ) {
  48.     case '+':
  49.         curr_pos++ ;
  50.         val += ParseExpression( ) ;
  51.         break ;
  52.     case '-':
  53.         curr_pos++ ;
  54.         val -= ParseExpression( ) ;
  55.         break ;
  56.     case '*':
  57.         curr_pos++ ;
  58.         val *= ParseExpression( ) ;
  59.         break ;
  60.     case '/':
  61.         curr_pos++ ;
  62.         val /= ParseExpression( ) ;
  63.         break ;
  64.     }
  65.     return val ;
  66. }
  67. double ParseFactor( )
  68. {
  69.     register double val = 0 ;
  70.     register double val2 ;
  71.     register int has_sign = FALSE ;
  72.     
  73.     if( *curr_pos == '-' ) {
  74.         has_sign = TRUE ;
  75.         curr_pos++ ;
  76.     }
  77.     
  78.     if( *curr_pos != '(' ) {
  79.         /* determine whether this is an address or not */
  80.         if( IsDigit( *curr_pos ) || *curr_pos == '.' ) {
  81.             val = ParseValue( ) ;
  82.         }else{
  83.             if( IsFunction( ) ) {
  84.                 val = CallFunction( ) ;
  85.             }else{
  86.                 val = ParseAddress( ) ;
  87.             }
  88.         }
  89.  
  90.         switch( *curr_pos ) {
  91.         case '^':
  92.             curr_pos++ ;
  93.             val2 = ParseFactor( ) ;
  94.             val = pow( val, val2 ) ;
  95.             break ;
  96.         case '*':
  97.             curr_pos++ ;
  98.             val2 = ParseFactor( ) ;
  99.             val *= val2 ;
  100.             break ;
  101.         case '/':
  102.             curr_pos++ ;
  103.             val2 = ParseFactor( ) ;
  104.             val /= val2 ;
  105.             break ;
  106.         }
  107.     }else{
  108.         curr_pos++ ;
  109.         val = ParseExpression( ) ;
  110.         if( *curr_pos == ')' ) {
  111.             curr_pos++ ;
  112.         }else{
  113.             parse_err = MISMATCHED_PARENTHESIS ;
  114.         }
  115.     }
  116.     
  117.     return ( has_sign ? -( val ):val ) ;
  118. }
  119. double ParseValue( )
  120. {
  121.     register double val = 0 ;
  122.     
  123.     if( IsDigit( *curr_pos ) || ( *curr_pos == '.' ) ) {
  124.         val = atof( ) ;
  125.     }else{
  126.         parse_err = INVALID_NUMBER ;
  127.     }
  128.     return val ;
  129. }
  130. double ParseAddress( )
  131. {
  132.     register int row ;
  133.     register int column ;
  134.     register double val = 0 ;
  135.     
  136.     column = GetColumn( ) ;
  137.     row = GetRow( ) ;
  138.     
  139.     if( ( row > MAX_ROWS ) || ( column > MAX_COLUMNS ) ) {
  140.         parse_err = ADDRESS_TOO_LARGE ;
  141.     }else{
  142.         val = curr_sheet_ptr->sheet_data[row-1][column-1].value ;
  143.     }
  144.     return val ;
  145. }
  146. int GetRow( )
  147. {
  148.     register int row ;
  149.     
  150.     if( IsDigit( *curr_pos ) ) {
  151.         row = *curr_pos - '0' ;
  152.     }else{
  153.         parse_err = INVALID_ADDRESS ;
  154.     }
  155.     curr_pos++ ;
  156.     
  157.     return row ;
  158. }
  159. int GetColumn( )
  160. {
  161.     register int column ;
  162.     
  163.     if( IsAlpha( *curr_pos ) ) {
  164.         if( *curr_pos >= 'a' ) {
  165.             column = ( *curr_pos - 'a' ) + 1 ;
  166.         }else{
  167.             column = ( *curr_pos - 'A' ) + 1 ;
  168.         }
  169.     }else{
  170.         parse_err = INVALID_ADDRESS ;
  171.     }
  172.     curr_pos++ ;
  173.     
  174.     return column ;
  175. }
  176. int IsFunction( )
  177. {
  178.     register unsigned char *p ;
  179.     
  180.     p = curr_pos ;
  181.     while( IsAlpha( *p ) || IsDigit( *p ) ) {
  182.         p++ ;
  183.     }
  184.     return ( *p == '(' ) ? TRUE:FALSE ;
  185. }
  186. double CallFunction( )
  187. {
  188.     unsigned char fun_name[32] ;
  189.     register unsigned char *p ;
  190.     register int fun_number ;
  191.     register double value ;
  192.     register ARG_PTR args ;
  193.     
  194.     p = fun_name ;
  195.     
  196.     while( IsAlpha( *curr_pos ) || IsDigit( *curr_pos ) ) {
  197.         *p = toupper( *curr_pos ) ;
  198.         p++; curr_pos++;
  199.     }
  200.     *p = '\0' ;
  201.     curr_pos++ ;
  202.     
  203.     args = BuildArg( ) ;
  204.     
  205.     if( ( fun_number = Lookup( fun_name ) ) > -1 ) {
  206.         value = (*fun_table[fun_number].fun_ptr)( args ) ;
  207.     }else{
  208.         parse_err = INVALID_FUNCTION ;
  209.     }
  210.     DestroyArgs( args ) ;
  211.     return value ;
  212. }
  213. int Lookup( fun_name )
  214. unsigned char *fun_name ;
  215. {
  216.     register int i = 0 ;
  217.     
  218.     while( fun_table[i].fun_name[0] != 0 ) {
  219.         if( !strcmp( fun_name, fun_table[i].fun_name ) ) {
  220.             return i ;
  221.         }
  222.         i++ ;
  223.     }
  224.     return -1 ;
  225. }
  226. ARG_PTR BuildArg( )
  227. {
  228.     int error ;
  229.     ARG_PTR first_arg_ptr = NULL, last_arg_ptr = NULL, next_arg_ptr = NULL ;
  230.     
  231.     /* This needs to be changed so that recursive functions calls can be
  232.     made */
  233.     while( *curr_pos != ')' ) {
  234.         next_arg_ptr = GetArg( ) ;
  235.         next_arg_ptr->value = ParseExpression( ) ;
  236.         next_arg_ptr->type = VALUE_ARG ;
  237.         if( *curr_pos == ',' ) {
  238.             curr_pos++ ;
  239.         }
  240.         if( last_arg_ptr != NULL ) {
  241.             last_arg_ptr->next_arg = next_arg_ptr ;
  242.         }
  243.         if( first_arg_ptr == NULL ) {
  244.             first_arg_ptr = next_arg_ptr ;
  245.         }
  246.         last_arg_ptr = next_arg_ptr ;
  247.     }
  248.     next_arg_ptr->next_arg = NULL ;
  249.     
  250.     /* Now pass the last parenthesis by */
  251.     if( *curr_pos == ')' ) {
  252.         curr_pos++ ;
  253.         return first_arg_ptr ;
  254.     }else{
  255.         parse_err = MISMATCHED_PARENTHESIS ;
  256.         return NULL ;
  257.     }
  258. }
  259. double atof( )
  260. {
  261.     register double val = 0.0 ;
  262.     register double val2 = 0.0 ;
  263.     
  264.     if( IsDigit( *curr_pos ) || ( *curr_pos == '.' ) ) {
  265.         while( *curr_pos && IsDigit( *curr_pos ) ) {
  266.             val = ( val * 10 ) + ( *curr_pos - '0' ) ;
  267.             curr_pos++ ;
  268.         }
  269.         if( *curr_pos == '.' ) {
  270.             curr_pos++ ;
  271.         }
  272.         while( *curr_pos && IsDigit( *curr_pos ) ) {
  273.             val2 = ( val2 * 10 ) + ( *curr_pos - '0' ) ;
  274.             curr_pos++ ;
  275.         }
  276.         if( val2 != 0.0 ) {
  277.             while( val2 > 1 ) {
  278.                 val2 /= 10 ;
  279.             }
  280.         }
  281.         val += val2 ;
  282.     }else{
  283.         parse_err = INVALID_NUMBER ;
  284.     }
  285.     return val ;
  286.  
  287. }
  288. void ftoa( val, buffer )
  289. double val ;
  290. unsigned char *buffer ;
  291. {
  292.     long whole ;
  293.     Str255 buff ;
  294.     Str255 tmp ;
  295.     int has_sign ;
  296.     int prec = /*curr_precision*/5 ;
  297.  
  298.     has_sign = ( val < 0 ) ? TRUE:FALSE ;
  299.     val = ( val<0 ) ? -val:val  ;  /* <- */
  300.     whole = val/1 ;
  301.     NumToString( whole, buffer ) ;
  302.     /* convert into c string in buffer */
  303.     BlockMove( &buffer[1], buff, buffer[0] ) ;
  304.     buff[buffer[0]] = 0 ;  /* 0 terminate buffer */
  305.     val -= whole ;
  306.     if( prec ) {
  307.         do{
  308.             val *= 10.0 ;
  309.         }while( --prec ) ;
  310.         whole = val ;
  311.         NumToString( whole, buffer ) ;
  312.         /* convert into c string in buffer */
  313.         BlockMove( &buffer[1], tmp, buffer[0] ) ;
  314.         tmp[buffer[0]] = 0 ;  /* 0 terminate buffer */
  315.         strcat( buff, "." ) ;
  316.         strcat( buff, tmp ) ;
  317.     }
  318.     if( has_sign ) {
  319.         tmp[0] = '-' ;
  320.         tmp[1] = '\0' ;
  321.         strcat( tmp, buff ) ;
  322.         strcpy( &buffer[1], tmp ) ;
  323.         buffer[0] = strlen( tmp ) ;
  324.     }else{
  325.         strcpy( &buffer[1], buff ) ;
  326.         buffer[0] = strlen( buff ) ;
  327.     }
  328.     
  329.     return ;
  330. }
  331. double GetFloat( formula, error )
  332. unsigned char *formula ;
  333. int *error ;
  334. {
  335.     register double value ;
  336.  
  337.     /* convert into c string in buffer */
  338.     BlockMove( &formula[1], buffer, formula[0] ) ;
  339.     buffer[formula[0]] = 0 ;  /* 0 terminate buffer */
  340.     
  341.     curr_pos = buffer ;
  342.     parse_err = 0 ;
  343.     
  344.     value = atof( ) ;
  345.     
  346.     *error = parse_err ;        /* Set error flag */
  347.     
  348.     return ( value ) ;
  349. }
  350. ARG_PTR GetArg( )
  351. {
  352.     register int i ;
  353.     
  354.     for( i=0;i<30;i++){
  355.         if( arg_free_pool[i].in_use == FREE_ARG ) {
  356.             arg_free_pool[i].in_use = IN_USE ;
  357.             return &arg_free_pool[i] ;
  358.         }
  359.     }
  360.     return NULL ;
  361. }
  362. void DestroyArgs( arg_ptr )
  363. ARG_PTR arg_ptr ;
  364. {
  365.     if( arg_ptr != NULL ) {
  366.         PutArg( arg_ptr ) ;
  367.         while( arg_ptr->next_arg != NULL ) {
  368.             arg_ptr = arg_ptr->next_arg ;
  369.             PutArg( arg_ptr ) ;
  370.         }
  371.     }
  372.     return ;
  373. }
  374. void PutArg( arg_ptr )
  375. ARG_PTR arg_ptr ;
  376. {
  377.     arg_ptr->in_use = FREE_ARG ;
  378.     return ;
  379. }
  380.